﻿using DataModels.Models;
using DataModels.Models.DHIS;
using DHISInteroperability;
using DHISInteroperability.DataTransfer;
using GenericTools;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

namespace ReportingManagement.Components.DHIS
{
    /// <summary>
    /// Interaction logic for DatasetComparer.xaml
    /// </summary>
    public partial class DatasetComparer : Window
    {
        public const int FACILITY_LEVEL = 1;
        public const int DISTRICT_LEVEL = 2;
        public const int REGION_LEVEL = 3;
        public const int NATION_LEVEL = 4;

        private List<Region> regions;
        private UserInformation user;
        private GenericTools.Models.OtherSystem otherSystem = null;

        public DatasetComparer()
        {
            InitializeComponent();

            var model = new DatasetComparerViewModel();
            var months = GetMonths();
            var years = GetYears();
            var aggregationLevels = GetReportAggregation();

            cboStartYear.ItemsSource = years;
            cboStartMonth.ItemsSource = months;
            
            cboEndYear.ItemsSource = years;
            cboEndMonth.ItemsSource = months;

            cboReportAggregation.ItemsSource = aggregationLevels;
            this.DataContext = model;
        }

        public DatasetComparer(UserInformation user)
        {
            InitializeComponent();

            var model = new DatasetComparerViewModel();
            var months = GetMonths();
            var years = GetYears();
            var aggregationLevels = GetReportAggregation();

            cboStartYear.ItemsSource = years;
            cboStartMonth.ItemsSource = months;

            cboEndYear.ItemsSource = years;
            cboEndMonth.ItemsSource = months;

            cboReportAggregation.ItemsSource = aggregationLevels;
            this.DataContext = model;
            this.user = user;

            // Start with populating the list of organization unit.
            cboReportAggregation.SelectedValue = FACILITY_LEVEL;
            cboReportAggregation_SelectionChanged(null, null);
        }

        private void btnExportToExcel_Click(object sender, RoutedEventArgs e)
        {

        }
        
        private void btnGetReport_Click(object sender, RoutedEventArgs e)
        {
            if (lstReports.SelectedItem == null)
            {
                MessageBox.Show(this, "Please select Report in the left panel");
                return;
            }
            else
            {
                // Disable all user controls associated with this operation.
                btnGetReport.IsEnabled = false;
                btnExportToExcel.IsEnabled = false;
                lstReports.IsEnabled = false;

                try
                {
                    // Based on the selection we are going to get the DHIS and IQSMS
                    // reports and format them to our bound view model object
                    if (otherSystem == null)
                    {
                        var dhis2 = GenericTools.Models.OtherKnownSystem.DHIS2;
                        otherSystem = GenericTools.Models.OtherSystem.GetOtherSystem(dhis2);
                    }

                    var model = this.DataContext as DatasetComparerViewModel;
                    DataTable dataTable = null;
                    string organizationUnit = null;
                    switch (model.AggregationLevel)
                    {
                        case FACILITY_LEVEL:
                            dataTable = Utilities.GetFacilityReport(model.OrganizationUnit as string,
                                model.ReportId, model.StartYear, model.StartMonth, model.EndYear,
                                model.EndMonth);
                            var facilityOtherDetails = Utilities.GetOtherSystemsFacilityDetails(otherSystem.Id, model.OrganizationUnit as string);
                            organizationUnit = facilityOtherDetails.FacilityCode;
                            break;

                        case DISTRICT_LEVEL:
                            dataTable = Utilities.GetDistrictReport((int)model.OrganizationUnit,
                                model.ReportId, model.StartYear, model.StartMonth, model.EndYear,
                                model.EndMonth);
                            var districtOtherDetails = Utilities.GetOtherSystemsDistrictDetails(otherSystem.Id, (int)model.OrganizationUnit);
                            organizationUnit = districtOtherDetails.DistrictCode;
                            break;

                        case REGION_LEVEL:
                            dataTable = Utilities.GetRegionReport((int)model.OrganizationUnit,
                                model.ReportId, model.StartYear, model.StartMonth, model.EndYear,
                                model.EndMonth);
                            var regionOtherDetails = Utilities.GetOtherSystemsRegionDetails(otherSystem.Id, (int)model.OrganizationUnit);
                            organizationUnit = regionOtherDetails.RegionCode;
                            break;

                        case NATION_LEVEL:
                            dataTable = Utilities.GetNationReport(model.ReportId, model.StartYear,
                                model.StartMonth, model.EndYear, model.EndMonth);
                            break;
                    }

                    ReportDataSetLink reportDataSetLink = Utilities.GetReportDataSetLink(model.ReportId);
                    var agent = new DHISInteroperability.Authentication.AuthorizationAgent("admin", "district");
                    var baseUrl = "https://apps.dhis2.org/demo";

                    DataTransferManager dataTransferManager = new DataTransferManager(baseUrl, agent);
                    string startDate = string.Format("{0}-{1}-01", model.StartYear, model.StartMonth);
                    string endDate = string.Format("{0}-{1}-{2}", model.EndYear, model.EndMonth, DateTime.DaysInMonth(model.EndYear, model.EndMonth));

                    dataValueSet dataSetValues = dataTransferManager.GetDataValues(
                        new List<string> { reportDataSetLink.DataSetId },
                        new List<string> { organizationUnit }, startDate, endDate);

                    DHISInteroperability.Resources.dataSet dataset = dataTransferManager.GetDataSet(
                        reportDataSetLink.DataSetId, "dataElements[id,name]");

                    model.DatasetComparerIndicatorValues.Clear();

                    // Now at this point we have everything we need, we just going to build data grid elements
                    // which we'll bind them.
                    // These elements are the objects of DatasetComparerIndicatorValue
                    // which contains IQSMS and DHIS indicator names and values.

                    // Going through the report indicators
                    foreach (DataRow row in dataTable.Rows)
                    {
                        var element = new DatasetComparerIndicatorValue
                        {
                            IndicatorDescription = row[0].ToString(),
                            IQSMSValue = int.Parse(row[1].ToString())
                        };

                        // Now let's find its associated DHIS data element.
                        foreach (var elementLink in reportDataSetLink.ReportDataSetElementsLinks)
                        {
                            if (elementLink.ReportIndicator.DataDescription == element.IndicatorDescription)
                            {
                                // Here we're setting the name of indicators
                                foreach (var dataElement in dataset.dataElements)
                                {
                                    if (dataElement.id == elementLink.DataElementId)
                                    {
                                        element.DataElementDescription = dataElement.name;
                                        break;
                                    };
                                }

                                // In case there is no data for the selected time span
                                if (dataSetValues.dataValue != null)
                                {
                                    foreach (var dv in dataSetValues.dataValue)
                                    {
                                        if (dv.dataElement == elementLink.DataElementId)
                                        {
                                            int value;
                                            bool converted = int.TryParse(dv.value, out value);
                                            if (converted) element.DHISValue = value;
                                            else element.DHISValue = null;
                                            break;
                                        }
                                    }
                                }
                                break;
                            }
                        }

                        model.DatasetComparerIndicatorValues.Add(element);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(this,
                        ex.Message, "Operation could not be completed", MessageBoxButton.OK,
                        MessageBoxImage.Warning);
                }
                finally
                {
                    // Enabling all user control associated with this operation.
                    btnGetReport.IsEnabled = true;
                    btnExportToExcel.IsEnabled = true;
                    lstReports.IsEnabled = true;
                }
            }
        }

        private Dictionary<int, string> GetMonths()
        {
            Dictionary<int, string> months = new Dictionary<int, string>();
            for (int i = 1; i <= 12; i++)
            {
                string date = string.Format("1987-{0}-1", i);
                DateTime targetDate = DateTime.Parse(date);
                string monthText = targetDate.ToString("MMM");
                months[i] = monthText;
            }
            return months;
        }

        private List<int> GetYears()
        {
            var years = new List<int>();
            // This will be just the last three years
            var thisYear = DateTime.Now.Year;

            years.Add(thisYear);
            years.Add(--thisYear);
            years.Add(--thisYear);
            years.Add(--thisYear);

            return years;
        }

        private Dictionary<int, string> GetReportAggregation()
        {            
            var aggregations = new Dictionary<int, string>();
            aggregations[FACILITY_LEVEL] = "Facility Level";
            aggregations[DISTRICT_LEVEL] = "District Level";
            aggregations[REGION_LEVEL] = "Region Level";
            aggregations[NATION_LEVEL] = "National Level";

            return aggregations;
        }

        private void cboReportAggregation_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (regions == null)
            {
                regions = Utilities.GetDetailedAllRegions(user.SupportingPartnerId, user.UserSignature);
            }

            if (cboReportAggregation.SelectedValue != null)
            {
                int level = (int)cboReportAggregation.SelectedValue;
                switch (level)
                {
                    case FACILITY_LEVEL:
                        var facilities = new List<DataModels.Models.Facility>();
                        foreach (var region in regions)
                        {
                            foreach (var district in region.Districts)
                            {
                                foreach (var facility in district.Facilities) facilities.Add(facility);
                            }
                        }
                        cboOrganisationUnit.DisplayMemberPath = "FacName";
                        cboOrganisationUnit.SelectedValuePath = "FacCode";
                        cboOrganisationUnit.ItemsSource = facilities.OrderBy(f => f.FacName);
                        //cboOrganisationUnit.IsEnabled = true;
                        break;

                    case DISTRICT_LEVEL:
                        var districts = new List<DataModels.Models.District>();
                        foreach (var region in regions)
                        {
                            foreach (var district in region.Districts) districts.Add(district);
                        }
                        cboOrganisationUnit.DisplayMemberPath = "District1";
                        cboOrganisationUnit.SelectedValuePath = "DistrictNo";
                        cboOrganisationUnit.ItemsSource = districts.OrderBy(d => d.District1);
                        //cboOrganisationUnit.IsEnabled = true;
                        break;

                    case REGION_LEVEL:
                        cboOrganisationUnit.DisplayMemberPath = "RegionName";
                        cboOrganisationUnit.SelectedValuePath = "RegionNo";
                        cboOrganisationUnit.ItemsSource = regions.OrderBy(r => r.RegionName);
                        //cboOrganisationUnit.IsEnabled = true;
                        break;

                    case NATION_LEVEL:
                        //cboOrganisationUnit.IsEnabled = false;
                        break;
                }
            }
        }
    }
}
